home *** CD-ROM | disk | FTP | other *** search
- VERSION 1.0 CLASS
- BEGIN
- MultiUse = -1 'True
- END
- Attribute VB_Name = "SortedCollection"
- Attribute VB_Creatable = False
- Attribute VB_Exposed = False
- '=================================================
- 'SortedCollection class for Visual Basic
- '--------------------------------------------------------------------------------------
- '12/28/95
- 'SortedCollection class description.
- '
- 'I have found this to be a most useful class for writing
- 'database apps in VB 4.0. The key value for the members of
- 'a SortedCollection class actually form a searchable index,
- 'unlike the unsorted key values of the generic Collection
- 'object. The only catch is that you *must* specify a key for
- 'each member. SortedCollection is lenient and will accept
- 'objects and variables of any type - the details are left to the
- 'programmer.
- '
- 'Also, you must explicitly use the Item method to retrieve items
- 'from the SortedCollection. The following will not work:
- '
- ' Dim MySortList as SortedCollection
- ' .
- ' .
- ' .
- ' SomeVariable = MySortList(1).SomeProperty 'wont work
- ' SomeVariable = MySortList.Item(1).SomeProperty 'works
- '
- 'SortedCollection also has two new helpful methods: Key(V) and
- 'IndexOf(V). Key(V) will return the key name for the item at
- 'the Vth position (or redundantly, returns Key itself if V is a
- 'string). IndexOf will return the position of the item whose
- 'key is V.
- '
- 'Example:
- ' MySortList.Add SomeObject, Object.Name
- ' Debug.Print MySortList.IndexOf(Object.Name) 'gives new position
- '
- ' Debug.Print MySortList.Key(MySortList.Count) 'gives key of last
- ' 'item in collection
- '
- 'Please note that the key is stored in ALLCAPS, and you
- 'cannot add keys 'german' and 'German' to the same SortedCollection.
- 'Note that if you use numbers as keys, 100 comes before 20 in the keys
- 'since the sort is alphabetic, not numeric. If this is a problem, you
- 'may want to change the default behavior programmatically.
- '
- 'How do we deal with duplicate index values? The ErrorAction property, which
- 'may be set at runtime, controls the action taken when the user tries to add an
- 'item to the collection. By default, it raises the error before VBA does. If you set the
- 'ErrorAction to ERRACTION_INFORM, SortedCollection will post a message box
- 'telling the user that it will not accept the new item. ERRACTION_IGNORE will pass
- 'over the attempted addition, and ERRACTION_REPLACE will replace the old
- 'item at that position with the new one.
- '
- 'Of course, you can always test to see if a key is already in use by the SortedCollection.
- 'If IndexOf(SomeKey) = 0, then it is OK to add the new item to the SortedCollection,
- 'Alternatively, I have provided a simple wrapper to improve readability in the
- 'calling procedure: KeyInUse()
- '
- 'I order to simplify my class, SortedCollection encapsulates two
- 'Collections, one which holds the actual objects in the
- 'collection, and one which redundantly holds the indexes as
- 'objects. Since VB does not provide an easy way to retrieve the
- 'key value from a particular position, the synchronized key
- 'collection allows easy retrieval.
- '
- 'I'm sure there are many improvements and additions which could be made
- 'to this crude SortedCollection class. I would like to hear from you.
- 'You may use the code in this class for free, and the author makes no
- 'warranty as to its safety or suitability for any purpose whatsoever.
- 'You may send improvements, suggestions and additions to:
- '
- 'Chris Velazquez
- '74073.1566@compuserve.com
-
- Option Explicit
- Private prvCollection As Collection
- Private prvSynchro As Collection
- Private prvDuplicateIndexErrorAction As Long
-
- Const ERR_DUPINDEX = 457
- Const ERR_METHOD_NOT_APPLIC = 438
-
- Const ERRACTION_MIN = 0
- Const ERRACTION_RAISE = 0 'default (and safest!)
- Const ERRACTION_INFORM = 1
- Const ERRACTION_IGNORE = 2
- Const ERRACTION_REPLACE = 3
- Const ERRACTION_MAX = 3
- '
- '
-
- Public Sub Add(V As Variant, K As Variant) 'Key not optional!!!
-
- Dim NewKey As String
- Dim NewSynchroItem As String
- Dim Hi, Lo, Center As Variant
-
- NewSynchroItem = CStr(K)
- NewKey = UCase(NewSynchroItem)
-
- Select Case Count
-
- Case 0
- prvCollection.Add V, NewKey
- prvSynchro.Add NewSynchroItem, NewKey
-
- Case 1
- If Key(1) > NewKey Then
- prvCollection.Add Item:=V, Key:=NewKey, Before:=1
- prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=1
-
- ElseIf Key(1) < NewKey Then
- prvCollection.Add Item:=V, Key:=NewKey, After:=Count
- prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, After:=1
-
- Else
- HandleDuplicateIndex V, K
- Exit Sub
-
- End If
-
- Case Else
- Hi = Count
- Lo = 1
-
- If Key(Lo) > NewKey Then 'add to beginning
- prvCollection.Add Item:=V, Key:=NewKey, Before:=1
- prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=1
-
- ElseIf Key(Hi) < NewKey Then 'add to end
- prvCollection.Add Item:=V, Key:=NewKey, After:=Count
- prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, After:=Hi
-
- Else 'play Hi-Lo
-
- Do Until Hi = Lo + 1
- Center = (Hi + Lo) \ 2 'this rounds instead of truncates
- Select Case Key(Center)
-
- Case NewKey
- HandleDuplicateIndex V, K
- Exit Sub
-
- Case Is < NewKey
- Lo = Center
-
- Case Is > NewKey
- Hi = Center
-
- End Select
- Loop
-
- If K = Key(Hi) Or K = Key(Lo) Then
- HandleDuplicateIndex V, K
- Else
- prvCollection.Add Item:=V, Key:=NewKey, Before:=Hi
- prvSynchro.Add Item:=NewSynchroItem, Key:=NewKey, Before:=Hi
- End If
- End If
-
- 'end of cases
- End Select
- End Sub
-
- Public Sub Remove(V)
- prvCollection.Remove V
- prvSynchro.Remove V
- End Sub
-
- Public Function Count()
- Count = prvCollection.Count
- End Function
-
- Public Function Item(V As Variant) As Variant
- On Local Error Resume Next
- Item = prvCollection.Item(V) 'works only for variables
- If Err = ERR_METHOD_NOT_APPLIC Then
- Set Item = prvCollection.Item(V) 'works only for objects
- Else
- Err.Raise Err.Number
- End If
- End Function
-
- Private Sub Class_Initialize()
- Set prvCollection = New Collection
- Set prvSynchro = New Collection
- End Sub
-
- Public Function Key(V)
- Key = UCase(prvSynchro.Item(V))
- End Function
-
- Public Function KeyMixedCase(V)
- KeyMixedCase = prvSynchro.Item(V)
- End Function
-
- Public Sub Clear()
- Do Until Count = 0
- Remove 1
- Loop
- End Sub
-
- Public Function IndexOf(V)
- Dim SearchKey As String
- Dim Hi, Lo, Center
-
- 'Caution: using Key(IndexOf(blah)) may set up a recursion!
- SearchKey = UCase(V)
- If Count = 0 Then
- IndexOf = 0: Exit Function
-
- Else
- Lo = 1
- Hi = Count
-
- If SearchKey = Key(Hi) Then
- IndexOf = Hi: Exit Function
- ElseIf SearchKey = Key(Lo) Then
- IndexOf = Lo: Exit Function
- Else
- Do Until Hi <= Lo + 1
- Center = (Hi + Lo) \ 2
- Select Case SearchKey
- Case Key(Center)
- IndexOf = Center: Exit Function
- Case Is < Key(Center)
- Hi = Center
- Case Is > Key(Center)
- Lo = Center
- End Select
- Loop '(Hi <= Lo + 1)
-
- End If '(SearchKey)
-
- If SearchKey = Key(Hi) Then
- IndexOf = Hi
- ElseIf SearchKey = Key(Lo) Then
- IndexOf = Lo
- Else
- IndexOf = 0
- End If
-
- End If '(Count = 0)
- End Function
-
- Public Property Get ErrorAction() As Integer
- ErrorAction = prvDuplicateIndexErrorAction
- End Property
-
- Public Property Let ErrorAction(I As Integer)
- If I < ERRACTION_MIN Or I > ERRACTION_MAX Then
- MsgBox "SortedCollection.ErrorAction -- Invalid property value"
- Else
- prvDuplicateIndexErrorAction = I
- End If
- End Property
-
- Private Sub HandleDuplicateIndex(V As Variant, K As Variant)
-
- Select Case prvDuplicateIndexErrorAction
-
- Case ERRACTION_RAISE
- Err.Raise ERR_DUPINDEX
-
- Case ERRACTION_INFORM
- MsgBox "The key '" & CStr(K) & "' is already in use; cannot add item"
-
- Case ERRACTION_IGNORE
- 'Do nothing
-
- Case ERRACTION_REPLACE
- Remove K
- Add V, K
-
- End Select
-
- End Sub
-
- Public Function KeyInUse(V) As Boolean
- KeyInUse = Not (IndexOf(V) = 0)
- End Function
-